import 'package:dartz/dartz.dart';
import 'package:json_annotation/json_annotation.dart';

part 'api_result.g.dart';

/// 统一的API结果类型
typedef ApiResult<T> = Either<ApiFailure, T>;

/// API失败类型
abstract class ApiFailure {
  const ApiFailure(this.message, [this.code]);
  
  final String message;
  final String? code;
  
  @override
  String toString() => 'ApiFailure(message: $message, code: $code)';
}

/// 网络错误
class NetworkFailure extends ApiFailure {
  const NetworkFailure(super.message, [super.code]);
}

/// 服务器错误
class ServerFailure extends ApiFailure {
  const ServerFailure(super.message, [super.code]);
}

/// 认证失败
class AuthFailure extends ApiFailure {
  const AuthFailure(super.message, [super.code]);
}

/// 解析错误
class ParseFailure extends ApiFailure {
  const ParseFailure(super.message, [super.code]);
}

/// 统一的API响应模型
@JsonSerializable(genericArgumentFactories: true)
class ApiResponse<T> {
  const ApiResponse({
    required this.success,
    required this.message,
    this.data,
    this.code,
  });

  final bool success;
  final String message;
  final T? data;
  final String? code;

  factory ApiResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) => _$ApiResponseFromJson(json, fromJsonT);

  Map<String, dynamic> toJson(Object Function(T value) toJsonT) =>
      _$ApiResponseToJson(this, toJsonT);
}

/// 分页响应数据模型
@JsonSerializable(genericArgumentFactories: true)
class PaginatedResponse<T> {
  const PaginatedResponse({
    required this.items,
    required this.total,
    required this.page,
    required this.pageSize,
    required this.totalPages,
  });

  final List<T> items;
  final int total;
  final int page;
  final int pageSize;
  final int totalPages;

  factory PaginatedResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) => _$PaginatedResponseFromJson(json, fromJsonT);

  Map<String, dynamic> toJson(Object Function(T value) toJsonT) =>
      _$PaginatedResponseToJson(this, toJsonT);
}

/// API结果扩展方法
extension ApiResultX<T> on ApiResult<T> {
  /// 获取数据或null
  T? get dataOrNull => fold((_) => null, (data) => data);
  
  /// 获取错误或null
  ApiFailure? get failureOrNull => fold((failure) => failure, (_) => null);
  
  /// 是否成功
  bool get isSuccess => isRight();
  
  /// 是否失败
  bool get isFailure => isLeft();
  
  /// 当成功时执行
  void onSuccess(void Function(T data) action) {
    fold((_) {}, action);
  }
  
  /// 当失败时执行
  void onFailure(void Function(ApiFailure failure) action) {
    fold(action, (_) {});
  }
}

